Fork me on GitHub

Ubuntu18.04 Swarm集群搭建

Swarm简介

Swarm 是 Docker 官方提供的一款集群管理工具,用来管理 Docker 集群,它将若干台 Docker 主机抽象为一个整体,并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源。

Swarm 只是一个调度器(Scheduler)加路由器 (Router),Swarm 自己不运行容器,它只是接受 Docker 客户端发送过来的请求,调度适合的节点来运行容器,这意味着,即使 Swarm 由于某些原因挂掉了,集群中的节点也会照常运行,当 Swarm 重新恢复运行之后,它会收集重建集群信息。

Docker Engine 从 V1.12.0 版本开始,原生集成了 Docker Swarm,所以只要在每台机器上安装 Docker,就可以直接使用 Docker Swarm。

Swarm 和 Kubernetes 比较类似,但是更加轻,具有的功能也较 Kubernetes 更少一些。

Swarm会提供网络管理、负载均衡、基于DNS容器发现、集群状态管理、扩容缩容等功能,在DevOps流程层面,可以组合成发布、回滚应用、查看服务的状态、日志、终端,更改发布配置(例如环境变量、默认副本数等)等功能。这个层面Portainer这个开源项目,提供了更好用集群管理的UI界面和类似Kubernetes Apiserver设计的Docker集群API接口服务。

upload successful

Docker Swarm的资源抽象比较简单,在没有容器编排的情况下,我们主要使用Services,这个和Kubernetes上的Services有些不一样,可以理解为Services和Deployment的合体,用来管理和定义容器的调度和扩容等,也可以直接做端口映射,在容器集群里任意IP都可以访问。

集群规划

因为Manager节点只负责调度集群的Task,配置要求不高,可用3台低配置机器作为Manager节点,根据Raft算法,3台可以容许1台机器出问题,5台可以允许2台机器出问题,大家可以按需求部署。Worker节点的作用是运行业务容器。同时,在Manager和Worker节点上,会以容器方式部署机器监控和日志收集,上面还需要运行网络和存储插件。

IP地址 Swarm节点类型 主机名
192.168.56.111 manager m01
192.168.56.112 manager m02
192.168.56.113 manager m03
192.168.56.114 worker n01
192.168.56.115 worker n02

集群节点配置

笔者是用VirtualBox虚拟5台机器,作为运行Docker的宿主机。本节以下内容均是在m01上操作的。其他节点配置不再赘述,参考此m01节点的配置即可。

网络配置

每台宿主机需要启用仅主机(Host-Only)网络及网络地址转换(NAT)两张网卡

以m01为例,/etc/netplan/01-netcfg.yaml网络配置如下:

1
2
3
4
5
6
7
8
9
10
11
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: no
dhcp6: no
addresses: [192.168.56.111/24]
enp0s8:
dhcp4: yes
dhcp6: no

注意这里enp0s3就是仅主机(Host-Only)网络这个网卡,此网卡用于ssh连接我们的虚拟机,由于这里是virtualbox虚拟机无需配置网关,enp0s8就是网络地址转换(NAT)这个网卡,此网卡用于访问外网。

主机名及hosts

设置主机名 sudo vi /etc/hostname

1
m01

如果遇到重启机器后主机名被重置,可以再用sudo hostnamectl set-hostname xxx 设置

通过sudo vi /etc/host以添加以下内容

1
2
3
4
5
192.168.56.111 m01
192.168.56.112 m02
192.168.56.113 m03
192.168.56.114 n01
192.168.56.115 n02

设置国内软件源

备份sources.list,sudo cp /etc/apt/sources.list /etc/apt/sources.list.default

批量修改sources.list

1
2
3
sudo sed -i "s#us.archive.ubuntu.com/#mirrors.aliyun.com/#g" /etc/apt/sources.list

sudo sed -i "s#security.ubuntu.com/#mirrors.aliyun.com/#g" /etc/apt/sources.list

安装Docker

安装GPG证书

1
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

写入软件源信息

1
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

更新并安装Docker-CE

1
2
sudo apt-get -y update
sudo apt-get -y install docker-ce

若想要安装指定版本Docker,参照如下操作:

  • Step 1: 查找Docker-CE的版本:
1
2

sudo apt-cache madison docker-ce
  • Step 2: 安装指定版本的Docker-CE
1
sudo apt-get -y install docker-ce=[VERSION]

注意上面命令中的[VERSION]需要替换成你想要安装的docker版本,
比如这里我将[VERSION]替换为5:18.09.4~3-0~ubuntu-bionic,所以最终的安装命令是sudo apt-get -y install docker-ce=5:18.09.6~3-0~ubuntu-bionic

其他可选的Docker软件源还有清华大学Docker软件源

配置Docker镜像加速

1
2
3
4
sudo vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}

注意 insecure-registries是配置非https的镜像中心,比如我们自己搭建的一个docker私有镜像中心,是用http的话,就可以用insecure-registries指定。

修改docker.service配置

如果碰到Unable to proxy the request via the Docker socket,这个错误,建议可以在任意worker节点,docker服务配置,
upload successful

这里只要改集群中一个节点就可以了(如果是用portainer agent方式添加的endpoint)主要是要改ExecStart,暴露2375,笔者改的是n01节点上的/lib/systemd/system/docker.service

sudo vi /lib/systemd/system/docker.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// -H 0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always

# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3

# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s

# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this option.
TasksMax=infinity

# set delegate yes so that systemd does not reset the cgroups of docker containers


内容过多省略...

还可以改成

1
2
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix:// -H 0.0.0.0:2375 --containerd=/run/containerd/containerd.sock

1
2
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375 --containerd=/run/containerd/containerd.sock

sudo systemctl daemon-reload
sudo systemctl restart docker

重启docker服务

1
sudo systemctl restart docker

开始搭建Swarm集群

上述都是在做准备工作,接下来就正式开始搭建Swarm集群。

初始化Swarm集群

1
sudo docker swarm init --advertise-addr 192.168.56.111

初始化swarm集群

注意:上图显示的token仅作参考,具体需看实际情况,也请记下来

如果遗失可以通过下面两个命令,分别找回manager、worker的join token

1
2
3
sudo docker swarm join-token manager

sudo docker swarm join-token worker

集群添加manager节点

获取manager的join token

根据上一节给出的提示,在192.168.56.111(m01)上执行

1
sudo docker swarm join-token manager

集群添加manager节点

根据提示,若要将节点作为manager节点加入swarm集群,需执行如下命令:

1
docker swarm join --token SWMTKN-1-65q3om1lmrjrsvnbqug0qccf00ertneorskvmv86g05qzicc8w-1kuf57afgawuuz24h7gx4hycb 192.168.56.111:2377

添加manager节点到集群

根据我们的规划,我们要将m02、m03作为manager节点加入到swarm集群,所以我们在m02,m03上执行:

1
sudo docker swarm join --token SWMTKN-1-65q3om1lmrjrsvnbqug0qccf00ertneorskvmv86g05qzicc8w-1kuf57afgawuuz24h7gx4hycb 192.168.56.111:2377

注意:请根据实际情况进行修改,不要一模一样复制!

upload successful

upload successful

添加worker节点到集群

分别在n01,n02上执行如下命令:

1
docker swarm join --token SWMTKN-1-65q3om1lmrjrsvnbqug0qccf00ertneorskvmv86g05qzicc8w-978befgfbbuqzqzv2zbvcg8fk 192.168.56.111:2377

注意:请根据实际情况进行修改,不要一模一样复制!

upload successful

upload successful

查看节点状态

在任意manager节点上执行

1
sudo docker node ls

upload successful

从上图可以看到集群中有3个manager节点,2个worker

Swarm集群管理UI

建议每次都在固定的节点上运行,所以这里指定了node.hostname == m01

1
sudo docker service create --name portainer --publish 9000:9000 --replicas=1 --constraint 'node.hostname == m01' --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock --mount type=volume,src=portainer_data,dst=/data portainer/portainer

upload successful

Add Endpoints

添加一个Local Endpoint,由于portainer是运行在m01上的,所以就是添加m01

upload successful

upload successful

部署Portainer Agent

打开App Template,点击Poirtainer Agent
upload successful

给stack取个名字,然后单击deploy

upload successful

部署完成后,每个节点会起一个

upload successful

部署Portainer Agent的另外一个途径是在任意manager节点上,执行
以下命令

1
curl -L https://downloads.portainer.io/agent-stack.yml -o agent-stack.yml && docker stack deploy --compose-file=agent-stack.yml portainer-agent

添加其他Endpoint

这里以添加m02为例,Endpoint的名称我们就填m02这个主机名好了,然后就是要填写Endpoint URL,就填m02节点的IP地址以及Portainer Agent的端口号,即192.168.56.112:9001

upload successful

所有Endpoint添加完毕

upload successful

这里的m01也可以删掉后,用Agent来添加

镜像中心设置

当镜像中心是需要身份认证的,那么可以在registries里添加一个镜像中心,输入镜像中心的用户名,密码即可,这样集群中的所有节点都能从该镜像中心拉取镜像了。由于篇幅,这里不再赘述跟截图了,读者可以自行尝试。

测试集群

  • 部署一个nginx service
1
sudo docker service create --name mynginx --replicas 3 -p 8088:80 nginx:alpine

upload successful

我们发现通过任意节点的8088端口都能访问,那是因为Ingress的特性使得请求可以转发到任何一台Worker或者Manager节点上,然后通过内置的routing mesh的Load Balancer通过LVS转发请求到Service的其中一个副本,一个值得注意的点是,就算这台Node上没有运行这个Service的容器。Load Balancer也会找到其他机器上存在的副本,这个主要是通过内置的DNS加LVS转发实现。

  • 扩容、缩容
1
sudo docker service scale mynginx=2
1
sudo docker service scale mynginx=3

附录

删除节点

删除manager节点

manager节点不能直接删除,需要先降级到worker节点再删除。

比如,这里我误把n02作为manager加入到集群,我想把n02改成worker节点。

upload successful

1
2
sudo docker node demote cu8f
sudo docker node rm cu8f

cu8f为节点ID的前缀

删除worker节点

1
sudo docker node rm [ID或HOSTNAME]

工作节点离开集群

在工作节点上执行

1
sudo docker swarm leave

工作节点离开集群后,节点状态就会变为Down,这样此节点就可以加入到另外一个swarm集群了。(原先的swarm集群manager节点上记得用sudo docker node rm xxx删除此节点)

创建overlay网络

1
docker network create --subnet=192.168.10.0/24 --attachable -d overlay my-net

QA

如何删除docker

通过sudo apt-get purge docker-ce,然后将/var/lib/docker目录删掉

参考资料

http://dockone.io/article/8808 房多多容器化和容器云实践
https://www.cnblogs.com/bigberg/p/8656963.html Docker Macvlan
https://cizixs.com/2017/02/14/network-virtualization-macvlan/ linux 网络虚拟化: macvlan
https://opsx.alibaba.com/guide?lang=zh-CN&document=69a2341e-801e-11e8-8b5a-00163e04cdbb ubuntu 18.04 (bionic) 配置 opsx 安装源